package calcite;

import com.sun.javafx.binding.StringFormatter;
import org.apache.calcite.plan.hep.HepPlanner;
import org.apache.calcite.plan.hep.HepProgramBuilder;
import org.apache.calcite.rel.rules.FilterJoinRule;


import java.sql.*;
import java.util.Properties;

public class CsvTest2 {

  public static void main(String[] args) throws SQLException {
    String sql = "select * from EMPS";

    Properties info = new Properties();
    info.setProperty("model", "inline:"
            + "{\n"
            + "  version: '1.0',\n"
            + "  defaultSchema: 'mySchema',\n"
            + "   schemas: [\n"
            + "     {\n"
            + "       name: 'mySchema',\n"
            + "       tables: [\n"
            + "         {\n"
            + "           name: 'largeTable',\n"
            + "           type: 'custom',\n"
            + "           factory: 'org.apache.calcite.adapter.csv.CsvSchemaFactory',\n"
            + "           operand: {\n"
            + "             directory: 'EMPS.csv'\n"
            + "           }\n"
            + "         }\n"
            + "       ]\n"
            + "     }\n"
            + "   ]\n"
            + "}");
    try (Connection connection = DriverManager.getConnection("jdbc:calcite:", info)) {
      Statement statement = connection.createStatement();
      ResultSet resultSet = statement.executeQuery(sql);

      while(resultSet.next()){
        int empno = resultSet.getInt(1);
        String name = resultSet.getString(2);
        int deptno = resultSet.getInt(3);
        String gender = resultSet.getString(4);
        String city = resultSet.getString(5);
        int empid = resultSet.getInt(6);
        int age = resultSet.getInt(7);
        boolean slacker = resultSet.getBoolean(8);
        boolean manager = resultSet.getBoolean(9);
        Date joinDate = resultSet.getDate(10);

        String txt = String.format("empno=%d,name=%s,deptno=%d,gender=%s,city=%s,empid=%d,age=%d,slacker=%b,manager=%b,joinDate=%tF",empno,name,deptno,gender,city,empid,age,slacker,manager,joinDate);
        System.out.println(txt);
      }

      HepProgramBuilder builder = new HepProgramBuilder();
     // builder.addRuleInstance(FilterJoinRule.FilterIntoJoinRule); //note: 添加 rule
      HepPlanner hepPlanner = new HepPlanner(builder.build());
      //hepPlanner.setRoot(relNode);
      //relNode = hepPlanner.findBestExp();
      /**
       * 初始化 HepProgram 对象；
       * 初始化 HepPlanner 对象，并通过 setRoot() 方法将 RelNode 树转换成 HepPlanner 内部使用的 Graph；
       * 通过 findBestExp() 找到最优的 plan，规则的匹配都是在这里进行。
       * 1. 初始化 HepProgram
       * 这几步代码实现没有太多需要介绍的地方，先初始化 HepProgramBuilder 也是为了后面初始化 HepProgram 做准备，HepProgramBuilder 主要也就是提供了一些配置设置和添加规则的方法等，常用的方法如下：
       *
       * addRuleInstance()：注册相应的规则；
       * addRuleCollection()：这里是注册一个规则集合，先把规则放在一个集合里，再注册整个集合，如果规则多的话，一般是这种方式；
       * addMatchLimit()：设置 MatchLimit，这个 rule match 次数的最大限制；
       * HepProgram 这个类对于后面 HepPlanner 的优化很重要，它定义 Rule 匹配的顺序，默认按【深度优先】顺序，它可以提供以下几种（见 HepMatchOrder 类）：
       *
       * ARBITRARY：按任意顺序匹配（因为它是有效的，而且大部分的 Rule 并不关心匹配顺序）；
       * BOTTOM_UP：自下而上，先从子节点开始匹配；
       * TOP_DOWN：自上而下，先从父节点开始匹配；
       * DEPTH_FIRST：深度优先匹配，某些情况下比 ARBITRARY 高效（为了避免新的 vertex 产生后又从 root 节点开始匹配）。
       * 这个匹配顺序到底是什么呢？对于规则集合 rules，HepPlanner 的算法是：从一个节点开始，跟 rules 的所有 Rule 进行匹配，匹配上就进行转换操作，这个节点操作完，再进行下一个节点，这里的匹配顺序就是指的节点遍历顺序（这种方式的优劣，我们下面再说）
       *
       *
       * 2. HepPlanner.setRoot（RelNode –> Graph）
       * 先看下 setRoot() 方法的实现：
       * // org.apache.calcite.plan.hep.HepPlanner
       * public void setRoot(RelNode rel) {
       *   //note: 将 RelNode 转换为 DAG 表示
       *   root = addRelToGraph(rel);
       *   //note: 仅仅是在 trace 日志中输出 Graph 信息
       *   dumpGraph();
       * }
       * HepPlanner 会先将所有 relNode tree 转化为 HepRelVertex，这时就构建了一个 Graph：将所有的 elNode 节点使用 Vertex 表示，Gragh 会记录每个 HepRelVertex 的 input 信息，这样就是构成了一张 graph。
       */
    }
  }

}

